class SmsClient
  class MobileFormatError < RuntimeError; end
  class EmptyContentError < RuntimeError; end
  class SmsError < RuntimeError; end

  URL = Rails.application.secrets.sms[:url]
  RESOURCE = RestClient::Resource.new(URL)

  DEFAULT_PAYLOAD = {
    command: 'MT_REQUEST',
    spid: Rails.application.secrets.sms[:spid],
    sppassword: Rails.application.secrets.sms[:sppassword],
    spsc: '00',
    dc: 15
  }.freeze

  class << self
    def send(mobile, content)
      payload = build_payload(mobile, content)
      resp = RESOURCE.post(payload)
      Rails.logger.debug(resp.body)
      raise SmsError unless resp.code == 200
      resp
    end

    private

    def build_payload(mobile, content)
      mobile = normalize_mobile(mobile)
      content = encode_content(content)
      DEFAULT_PAYLOAD.merge da: mobile, sm: content
    end

    def normalize_mobile(mobile)
      raise MobileFormatError unless mobile =~ /\A(?:86)?(1\d{10})\z/
      "86#{$1}"
    end

    def encode_content(content)
      raise EmptyContentError unless content and not content.empty?
      content.encode('GBK').unpack('H*')[0]
    end
  end
end